/* Endless Code Copyright (C) 2009 Jingul,Kim
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package ec.gfx.ui;

import java.util.LinkedList;

import ec.Result;
import ec.core.Caster;
import ec.core.Input;
import ec.core.event.Event;
import ec.core.event.MouseEvt;
import ec.gfx.GL;
import ec.gfx.Scene;
import ec.gfx.Transform;
import ec.gfx.ui.event.MouseListener;
import ec.util.Size;

/**
 * 모든 인터페이스에서 가장 기초가 되는 클래스입니다.
 * 
 * @since 2009
 * @version 1.0
 * @author <a href="mailto:jingul.kim@gmail.com">Jingul,Kim</a>
 */
public class Part extends Transform implements Caster {
	private LinkedList<MouseListener> mouse = new LinkedList<MouseListener>();
	
	protected static final Input input = new Input();

	private boolean m_visible = false;

	protected Pack parent;
	
	protected float w, h;
	
	public Part() {
	}

	@Override
	public Result pre(Scene scene) {
		if (m_visible) {
			super.pre(scene);
			GL.loadName(hashCode());
			return Result.OK;
		}

		return Result.NO;
	}
	
	@Override
	public Result post(Scene scene) {
		if(m_visible) {
			return super.post(scene);
		}
		
		return Result.NO;
	}

	/**
	 * 해당 파트의 가시 여부를 설정한다.
	 * 
	 * @param visible
	 */
	public void setVisible(boolean visible) {
		if (m_visible == visible) {
			return;
		}

		if (visible) {
			input.add(this);
		} else {
			input.remove(this);
		}

		m_visible = visible;
	}

	/**
	 * 해당 파트가 부모 파트에 추가되는 시점에 호출된다.
	 */
	public void addNotify() {
	}

	/**
	 * 해당 파트가 부모 파트에 제거되는 시점에 호출된다.
	 */
	public void removeNotify() {
	}
	
	/**
	 * 부모 파트의 크기가 변경시에 호출된다.
	 */
	protected void notifyResized() {
		
	}

	@Override
	public void processEvent(Event e) {
		if (e instanceof MouseEvt) {
			processMouseEvt((MouseEvt)e);
		}
	}
	
	public void processMouseEvt(MouseEvt e) {
		switch(e.getType()) {
		case MouseEvt.CLICK:
			// 포커징
			announceClick(e);
			break;
		case MouseEvt.DBCLICK:
			announceDbClick(e);
			break;
		case MouseEvt.DOWN:
			announceDown(e);
			break;
		case MouseEvt.UP:
			announceUp(e);
		}
	}
	
	/**
	 * 파트의 크기를 얻는다.
	 * @return 파트의 가로,세로폭을 포함한 클래스
	 */
	public Size getSize() {
		return new Size(w, h);
	}
	
	/**
	 * 해당 파트의 크기를 설정한다.
	 * 
	 * @param w 가로폭 크기
	 * @param h 세로폭 크기
	 */
	public void setSize(float w, float h) {
		this.w = w;
		this.h = h;
	}
	
	/**
	 * 파트의 가로폭의 크기를 설정한다.
	 * 
	 * @param w 가로폭 크기
	 */
	public void setWidth(float w) {
		this.w = w;
		set
	}
	
	/**
	 * 파트의 세로폭의 크기를 설정한다.
	 * 
	 * @param h 세로폭 크기
	 */
	public void setHeight(float h) {
		this.h =h;
	}
	
	public void setLocation(float x, float y) {
		m_matrix.set(12, x);
		m_matrix.set(13, y);
	}
	
	
	/**
	 * 
	 * @return 파트의 가로폭 크기
	 */
	public float getWidth() {
		return w;
	}
	
	/**
	 * 
	 * @return 파트의 세로폭 크기
	 */
	public float getHeight() {
		return h;
	}
	
	/**
	 * 해당 파트의 가시 여부를 확인한다.
	 * @return 보이는 경우 true, 아닐 경우는 false
	 */
	public boolean isVisible() {
		return m_visible;
	}
	
	private void announceClick(MouseEvt e) {
		for(MouseListener m: mouse) {
			m.click(e);
		}
	}
	
	private void announceDbClick(MouseEvt e) {
		for(MouseListener m: mouse) {
			m.dbclick(e);
		}
	}
	
	private void announceUp(MouseEvt e) {
		for(MouseListener m: mouse) {
			m.up(e);
		}
	}
	private void announceDown(MouseEvt e) {
		for(MouseListener m: mouse) {
			m.down(e);
		}
	}
	
	public void addMouseListener(MouseListener l) {
		mouse.add(l);
	}
	
	public void removeMouseListener(MouseListener l) {
		mouse.remove(l);
	}
}
